package com.senseauto.mediacodecdemo;

import android.content.Context;
import android.content.res.Configuration;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.util.Log;

import java.nio.ByteBuffer;
import java.util.LinkedList;

//Camera2 获取的到的是yuv的数据
public class YuvEncoderH264 {
    String TAG = "NV21EncoderH264";
    private int width, height;
    private int frameRate = 30;
    private MediaCodec mediaCodec;
    private com.senseauto.mediacodecdemo.EncoderListener encoderListener;
    private int type = TYPE_LANDSCAPE;
    public static int TYPE_LANDSCAPE = 1;
    public static int TYPE_PORTRAIT = 2;
    public boolean isRecoding = false;

    boolean flagSave = false;//保存yuv，调试看画面
    long frameCount = 0;
    private Context mContext;

    public YuvEncoderH264(Context context, int width, int height) {
        this.width = width;
        this.height = height;
        //平板横屏输出的是1920*1440，有点像正方形的尺寸
        Log.e(TAG, "width=" + width + " height=" + height);
        this.mContext = context;
        setScreenOrientationInfo();
        initMediaCodec();
    }
    public boolean getRecodingStatus(){
        return isRecoding;
    }
    public void recodingChange(){
        if(isRecoding){
            isRecoding = false;
        }else{
            isRecoding = true;
        }
    }
    public void setScreenOrientationInfo() {

        Configuration configuration = mContext.getResources().getConfiguration();
        if (configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            Log.e("NV21EncoderH264", "configuration : 横屏");
            type = TYPE_LANDSCAPE;
        } else {
            Log.e("NV21EncoderH264", "configuration : 竖屏屏");
            type = TYPE_PORTRAIT;
        }
    }

    private void initMediaCodec() {
        try {
            mediaCodec = MediaCodec.createEncoderByType("video/avc");
            //height和width一般都是照相机的height和width。
            MediaFormat mediaFormat = null;
            if (type == TYPE_LANDSCAPE) {//横屏
                mediaFormat = MediaFormat.createVideoFormat("video/avc", width, height);
            } else {//竖屏有旋转的操作
                //TODO 因为获取到的视频帧数据是逆时针旋转了90度的，所以这里宽高需要对调
                mediaFormat = MediaFormat.createVideoFormat("video/avc", height, width);
            }
            Log.e(TAG, "输入的参数 width="+width+" height="+height);
            //描述平均位速率（以位/秒为单位）的键。 关联的值是一个整数
            mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, width * height * 5);
            //描述视频格式的帧速率（以帧/秒为单位）的键。帧率，一般在15至30之内，太小容易造成视频卡顿。
            mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate);
            //色彩格式，具体查看相关API，不同设备支持的色彩格式不尽相同
            mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar);
            //关键帧间隔时间，单位是秒
            mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);
            mediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
            Log.e(TAG, "mediaCodec="+mediaCodec.getCodecInfo().toString());
            // 获取编码器输出格式
            MediaFormat outputFormat = mediaCodec.getOutputFormat();

            // 输出编码器的尺寸
            int width = outputFormat.getInteger(MediaFormat.KEY_WIDTH);
            int height = outputFormat.getInteger(MediaFormat.KEY_HEIGHT);

            Log.e(TAG, "编码器尺寸: 宽 = " + width + ", 高 = " + height);
            //开始编码
            mediaCodec.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }



    public void encoderH264(byte[] data) {
        try {
            //拿到输入缓冲区,用于传送数据进行编码
            ByteBuffer[] inputBuffers = mediaCodec.getInputBuffers();
            //拿到输出缓冲区,用于取到编码后的数据
            ByteBuffer[] outputBuffers = mediaCodec.getOutputBuffers();
            int inputBufferIndex = mediaCodec.dequeueInputBuffer(-1);
            //当输入缓冲区有效时,就是>=0
            if (inputBufferIndex >= 0) {
                ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
                inputBuffer.clear();
                //往输入缓冲区写入数据
                inputBuffer.put(data);
                //五个参数，第一个是输入缓冲区的索引，第二个数据是输入缓冲区起始索引，第三个是放入的数据大小，第四个是时间戳，保证递增就是
                mediaCodec.queueInputBuffer(inputBufferIndex, 0, data.length, System.nanoTime() / 1000, 0);
            }
            //测试时发现车机DSP芯片的编码队列就4个，一直空不出来新的，卡在这里了mediaCodec.dequeueOutputBuffer
            MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
            //拿到输出缓冲区的索引
            int outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 0);
            while (outputBufferIndex >= 0) {
                ByteBuffer outputBuffer = outputBuffers[outputBufferIndex];
                byte[] outData = new byte[bufferInfo.size];
                outputBuffer.get(outData);

                //outData就是输出的h264数据
                if (encoderListener != null) {
                    encoderListener.h264(outData);
                }
                mediaCodec.releaseOutputBuffer(outputBufferIndex, false);
                outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 0);
            }
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }

    public void setEncoderListener(com.senseauto.mediacodecdemo.EncoderListener listener) {
        encoderListener = listener;
    }

}
